package com.laboratory.serviceprovide.service.impl;

import com.Laboratory.pojo.user;
import com.Laboratory.service.userService;
import com.Laboratory.utilPojo.emailMessage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.laboratory.serviceprovide.constant.constantArgs;
import com.laboratory.serviceprovide.mapper.userMapper;
import com.laboratory.serviceprovide.util.MD5Util;
import com.laboratory.serviceprovide.util.emailUtil;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.shiro.SecurityUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author acok
 * @description:user实体类对应服务接口实现类
 * @Date 2022/12/5 9:44
 * @Version 1.0
 */
@DubboService(interfaceClass = userService.class,version = "1.0.0",timeout = 5000)
public class userServiceImpl implements userService {

    @Resource
    private userMapper userMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public user selectUserByName(String username) {
        return userMapper.selectUserByName(username);
    }

    @Override
    public List<String> getRoleListByName(String username) {
        return userMapper.getRoleListByName(username);
    }

    @Override
    public List<String> getAuthorityByName(String username) {
        return userMapper.getAuthorityListByName(username);
    }

    @Override
    public user getUserDetailByName(String username) {
        return userMapper.getUserDetailByName(username);
    }

    /**
               * @return: SQL语句update执行结果（int）
               * @param: username、oldPassword（修改前根据username、oldPassword校验当前登录信息）
               * @description: 当校验完成无问题后，执行更新操作
               * @Author: Acok
               * @mbggenerated 2022/12/15
               */
    @Override
    public int beforeUpdateUserPassword(String username, String oldPassword, String newPassword) {
        int result=-1;
        user user = userMapper.getUserDetailByName(username);
        if(MD5Util.md5Util(oldPassword,3,user.getSalt()).equals(user.getPassword())){
            result=userMapper.updateUserPassword(username,
                    MD5Util.md5Util(newPassword,3,user.getSalt()));
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getRoleList() {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        List<Map<String,Object>> roleList=null;
        if (ops.get(constantArgs.REDIS_ROLE_LIST_KEY)==null){
            roleList=userMapper.getRoleList();
            if(roleList.size()>0){
                ops.set(constantArgs.REDIS_ROLE_LIST_KEY,JSON.toJSONString(roleList),60*60*6,TimeUnit.SECONDS);
            }
        }else {
            roleList=JSON.parseObject(ops.get(constantArgs.REDIS_ROLE_LIST_KEY),new TypeReference<List<Map<String,Object>>>(){});
        }
        return roleList;
    }

    @Override
    public List<Map<String, Object>> getAuthorityList() {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        List<Map<String,Object>> authorityList=null;
        if(ops.get(constantArgs.REDIS_AUTHORITY_LIST_KEY)==null){
            authorityList=userMapper.getAuthorityList();
            if(authorityList.size()>0){
                ops.set(constantArgs.REDIS_AUTHORITY_LIST_KEY,JSON.toJSONString(authorityList),60*60*6,TimeUnit.SECONDS);
            }
        }else {
            authorityList=JSON.parseObject(ops.get(constantArgs.REDIS_AUTHORITY_LIST_KEY),new TypeReference<List<Map<String,Object>>>(){});
        }
        return authorityList;
    }

    @Override
    public List<user> getUserList() {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        List<user> userList = null;
        if(ops.get(constantArgs.REDIS_USER_LIST_KEY)==null){
            userList=userMapper.getUserList();
            if(userList.size()>0){
                ops.set(constantArgs.REDIS_USER_LIST_KEY, JSON.toJSONString(userList),60*60*6, TimeUnit.SECONDS);
            }
        }else {
            userList=JSON.parseObject(ops.get(constantArgs.REDIS_USER_LIST_KEY),new TypeReference<List<user>>(){});
        }
        return userList;
    }

    @Override
    @CacheEvict(value="users", allEntries=true,beforeInvocation = true)
    public int updateAccountState(String id, String state, String type) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        int result=0;
        switch (type){
            case constantArgs.UPDATE_ACCOUNT_TYPE_CODE:{
               result= userMapper.updateUserAccountStateById(state,id);
               if(result>0){
                   if(ops.get(constantArgs.REDIS_USER_LIST_KEY)!=null){
                       List<user> userList=JSON.parseObject(ops.get(constantArgs.REDIS_USER_LIST_KEY),new TypeReference<List<user>>(){});
                       assert userList != null;
                       for (user u:
                               userList) {
                           if (u.getId().equals(id)){
                               u.setState(state);
                           }
                       }
                       ops.set(constantArgs.REDIS_USER_LIST_KEY,JSON.toJSONString(userList),60*60*6,TimeUnit.SECONDS);
                   }
               }
               break;
            }
            case constantArgs.UPDATE_AUTHORITY_TYPE_CODE:{
                result= userMapper.updateUserAuthorityStateById(state,id);
                if(result>0){
                    if(ops.get(constantArgs.REDIS_AUTHORITY_LIST_KEY)!=null){
                        List<Map<String, Object>> authorityList = JSON.parseObject(ops.get(constantArgs.REDIS_AUTHORITY_LIST_KEY), new TypeReference<List<Map<String, Object>>>() {});
                        assert authorityList != null;
                        for (Map<String ,Object> map:
                             authorityList) {
                            if(map.get("id").equals(id)){
                                map.put("state",state);
                            }
                        }
                        ops.set(constantArgs.REDIS_AUTHORITY_LIST_KEY,JSON.toJSONString(authorityList),60*60*6,TimeUnit.SECONDS);
                    }
                }
                break;
            }
        }
        return result;
    }

    @Override
    public int updateUserRole(String id, String role) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        int i = userMapper.updateUserRole(id, role);
        if(i>0){
            if(ops.get(constantArgs.REDIS_USER_LIST_KEY)!=null){
                List<user> userList=JSON.parseObject(ops.get(constantArgs.REDIS_USER_LIST_KEY),new TypeReference<List<user>>(){});
                assert userList != null;
                for (user u:
                        userList) {
                    if (u.getId().equals(id)){
                        u.setRole(role);
                    }
                }
                ops.set(constantArgs.REDIS_USER_LIST_KEY,JSON.toJSONString(userList),60*60*6,TimeUnit.SECONDS);
            }
        }
        return i;
    }

    @Override
    public int deleteUserById(String id,String fromAccount,String passwordCode,String targetAccount) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        int result=userMapper.deleteUserById(id);
        if(result==1){
            if(ops.get(constantArgs.REDIS_USER_LIST_KEY)!=null) {
                List<user> userList = JSON.parseObject(ops.get(constantArgs.REDIS_USER_LIST_KEY), new TypeReference<List<user>>() {});
                assert userList!=null;
                int len=userList.size();
                for (int i=0;i<len;i++){
                    if (userList.get(i).getId().equals(id)){
                        userList.remove(i);
                        /*集合长度减1*/
                        len--;
                        /*将指针指向被删除元素坐标前一位元素保证下次循环指向已当前被替换的元素*/
                        i--;
                    }
                }
                ops.set(constantArgs.REDIS_USER_LIST_KEY,JSON.toJSONString(userList),60*60*6,TimeUnit.SECONDS);
            }
            emailMessage e=new emailMessage();
            e.setFromAccount(fromAccount);
            e.setFromPassword(passwordCode);
            e.setAddressAccount(targetAccount);
            e.setEmailTitle(constantArgs.ACCOUNT_DESTROY_TITLE);
            e.setEmailContent(constantArgs.ACCOUNT_DESTROY_CONTENT);
            try {
                emailUtil.sendEmail(e);
            } catch (MessagingException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    @Override
    public List<String> getAccountList() {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        List<String> usernameList=null;
        if(ops.get(constantArgs.REDIS_USERNAME_LIST_KEY)==null){
               usernameList=userMapper.getUserNameList();
               if(usernameList.size()>0){
                   ops.set(constantArgs.REDIS_USERNAME_LIST_KEY,JSON.toJSONString(usernameList),10*60,TimeUnit.SECONDS);
               }
        }else {
            usernameList=JSON.parseObject(ops.get(constantArgs.REDIS_USERNAME_LIST_KEY),new TypeReference<List<String>>(){});
        }
        return usernameList;
    }

    @Override
    public int createUser(user user) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        user.setRole("users");
        user.setState("1");
        user.setPassword(MD5Util.md5Util(user.getPassword(),3,user.getSalt()));
        int i = userMapper.createUser(user);
        if(i>0){
            if(ops.get(constantArgs.REDIS_USERNAME_LIST_KEY)!=null){
                List<String> usernameList=JSON.parseObject(ops.get(constantArgs.REDIS_USERNAME_LIST_KEY),new TypeReference<List<String>>(){});
                assert usernameList != null;
                usernameList.add(user.getAccount());
                ops.setIfPresent(constantArgs.REDIS_USERNAME_LIST_KEY,
                        JSON.toJSONString(usernameList),
                        10*60,TimeUnit.SECONDS);
            }
            if(ops.get(constantArgs.REDIS_USER_LIST_KEY)!=null){
                List<user> userList=JSON.parseObject(ops.get(constantArgs.REDIS_USER_LIST_KEY),new TypeReference<List<user>>(){});
                assert userList != null;
                user cacheUser=new user();
                cacheUser.setId(user.getId());
                cacheUser.setAccount(user.getAccount());
                cacheUser.setTelephone(user.getTelephone());
                cacheUser.setRole(user.getRole());
                cacheUser.setIdentity(user.getIdentity());
                cacheUser.setCreatetime(user.getCreatetime());
                cacheUser.setEmail(user.getEmail());
                cacheUser.setState(user.getState());
                userList.add(cacheUser);
                ops.set(constantArgs.REDIS_USER_LIST_KEY,JSON.toJSONString(userList),60*60*6,TimeUnit.SECONDS);
            }
        }
        return i;
    }

    @Override
    public int updateUserMessage(user user) {
        int result=0;
        user userByAccount = userMapper.getUserDetailByName(user.getAccount());
        if(userByAccount.getPassword().equals(MD5Util.md5Util(user.getPassword(),3,userByAccount.getSalt()))){
            result=userMapper.updateUserMessage(user);
            ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
            if(result>0) {
                if (ops.get(constantArgs.REDIS_USER_LIST_KEY) != null) {
                    List<user> userList=JSON.parseObject(ops.get(constantArgs.REDIS_USER_LIST_KEY),new TypeReference<List<user>>(){});
                    assert userList != null;
                    for (user u:
                            userList) {
                        if (user.getId().equals(u.getId())) {
                            u.setEmail(user.getEmail());
                            u.setIdentity(user.getIdentity());
                            u.setTelephone(user.getTelephone());
                        }
                    }
                    ops.set(constantArgs.REDIS_USER_LIST_KEY,JSON.toJSONString(userList),60*60*6,TimeUnit.SECONDS);
                }
            }
        }
        return result;
    }
}
